﻿using System;
using System.IO;
using UnityEngine;
using UnityEngine.Networking;
using xuni;

namespace xres
{


    public class FileDownloadHandler : DownloadHandlerScript
    {
        public string Err_Write_Out = "Err_Write_Out";
        public string Err_Size = "Err_Size";


        //保存路径
        string _fileSavePath = "";

        string _errType = "";
        public string ErrType { get { return _errType; } }

        FileStream _fs;

        /// <summary>
        /// 断点下载开始字节数
        /// </summary>
        long _breakpointBytes;

        /// <summary>
        /// 文件的总字节数
        /// </summary>
        long _totalBytes;
        public long TotalBytes { get { return _totalBytes; } }

        /// <summary>
        /// 已下载字节数(如果是断点下载, 也包括之前已下载的)
        /// </summary>
        long _haveDownBytes;
        public long HaveDownBytes { get { return _haveDownBytes; } }


        public FileDownloadHandler(string savePath)
            : base(new byte[8 * 1024])//缓冲大小
        {
            _fileSavePath = savePath;
        }

        /// <summary>
        /// 开始下载(发送http请求)前调用
        /// </summary>
        /// <param name="useBreakPoint"></param>
        public long PrepareDownload(bool useBreakPoint)
        {
            if (null != _fs)
                throw new Exception("fs not close, EndDownload not call");

            if (true) Debug.Log($"DownHandler: PrepareDownload, {_fileSavePath}");

            _errType = "";

            _totalBytes = 0;

            var dirPath = Path.GetDirectoryName(_fileSavePath);
            if (!Directory.Exists(dirPath))
                Directory.CreateDirectory(dirPath);

            _fs = File.Open(_fileSavePath, FileMode.OpenOrCreate);
            if (useBreakPoint)
            {
                //上次下到50%关了, 下次打开重新下载进度应该从50%处开始, 从0%开始会感觉是重新下载
                _haveDownBytes = _breakpointBytes = _fs.Seek(0, SeekOrigin.End);
            }
            else
            {
                _haveDownBytes = _breakpointBytes = 0;
            }

            return _breakpointBytes;
        }

        /// <summary>
        /// 下载结束时调用
        /// </summary>
        public void EndDownload()
        {
            if (true) Debug.Log($"DownHandler: EndDownload, {_fileSavePath}");

            //404或网络错误时: CompleteContent不会被调用, 这边要主动close下
            IOUtils.SafeClose(_fs);
            _fs = null;
        }




        /// <summary>
        /// 获取到本次要下载文件的大小. 注意断点下载返回的是剩余字节数, 不是完整文件大小
        /// </summary>
        protected override void ReceiveContentLength(int contentLength)
        {
            _totalBytes = _breakpointBytes + contentLength;
            if (false) Debug.Log($"DownHandler: ReceiveContentLength: content:{contentLength}, total:{_totalBytes}, {_fileSavePath}");
        }

        protected override float GetProgress()
        {
            return _haveDownBytes / (float)_totalBytes;
        }

        /// <summary>
        /// 数据下载回调
        /// </summary>
        protected override bool ReceiveData(byte[] data, int len)
        {
            if (data == null || data.Length < 1)
            {
                Debug.Log($"ReceiveData: len: {len}, {_fileSavePath}");
                return false;
            }

            if (_totalBytes <= 0) //404的时候, 不会调用ReceiveContentLength, 直接到ReceiveData
            {
                if (true) Debug.LogWarning($"DownHandler: ReceiveData: len: {len}, but no contentLen, {_fileSavePath}");
                IOUtils.FlushAndClose(_fs);
                _fs = null;
                return false;
            }

            if (null == _fs)
            {
                Debug.LogError($"fs null, PrepareDownload not invoke?");
                return false;
            }

            try
            {
                _fs.Write(data, 0, len);
                _haveDownBytes += len;
                if (false) Debug.Log($"ReceiveData: RecvLen: {len}, FileLen: {_fs.Length}, Pos: {_fs.Position}");

                return true; //要继续下载
            }
            catch (Exception ex)
            {
                _errType = Err_Write_Out;
                Debug.LogError($"{ex.StackTrace}");

                IOUtils.SafeClose(_fs);
                _fs = null;
            }

            return false;
        }

        protected override void CompleteContent()
        {
            //404和网络断开这种情况都不会被调用
            if (null == _fs)
            {
                Debug.LogError($"CompleteContent: fs null?");
                return;
            }

            IOUtils.FlushAndClose(_fs);
            _fs = null;

            if (_totalBytes != _haveDownBytes)
            {
                _errType = Err_Size;
                Debug.Log($"DownHandler: Complete: err size: except:{_totalBytes}, real:{_haveDownBytes}, {_fileSavePath}");
            }
            else
            {
                _errType = "";
                if (false) Debug.Log($"DownHandler: Complete: ok, {_fileSavePath}");
            }
        }


    } //end of class


}

